﻿using System;
using System.Diagnostics;
using UtilZ.Dotnet.WindowsDesktopEx.Base;

namespace UtilZ.Dotnet.WindowsDesktopEx.WPF
{
    /// <summary>
    /// 嵌套应用程序类
    /// </summary>
    public class WpfAppEmbedder : AppEmbedderAbs
    {
        private readonly System.Windows.FrameworkElement _containerControl;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="containerControl"></param>
        /// <param name="process">嵌入进程</param>
        /// <exception cref="ArgumentException"></exception>
        public WpfAppEmbedder(System.Windows.FrameworkElement containerControl, Process process)
            : base(process)
        {
            if (containerControl == null)
            {
                throw new ArgumentException(nameof(containerControl));
            }

            this._containerControl = containerControl;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="containerControl">容器控件</param>
        /// <param name="exePath">嵌入程序启动路径</param>
        /// <param name="findProcess">是否从进程列表中查找进程[true:从进程列表中查找,找到至少一个后,用找到的第一个进程;false:不从进程列表中查找,始终新启动一个进程]</param>
        /// <param name="arguments">启动参数</param>
        public WpfAppEmbedder(System.Windows.FrameworkElement containerControl, string exePath, bool findProcess, string arguments = "")
            : base(exePath, findProcess, arguments)
        {
            if (containerControl == null)
            {
                throw new ArgumentException(nameof(containerControl));
            }

            this._containerControl = containerControl;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="containerControl">容器控件</param>
        /// <param name="processStartInfo">嵌入程序进程启动信息</param>
        /// <param name="findProcess">是否从进程列表中查找进程[true:从进程列表中查找,找到至少一个后,用找到的第一个进程;false:不从进程列表中查找,始终新启动一个进程]</param>
        public WpfAppEmbedder(System.Windows.FrameworkElement containerControl, ProcessStartInfo processStartInfo, bool findProcess)
            : base(processStartInfo, findProcess)
        {
            if (containerControl == null)
            {
                throw new ArgumentException(nameof(containerControl));
            }

            this._containerControl = containerControl;
        }


        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="containerControl">容器控件</param>
        /// <param name="mainWindowHandle">主窗口句柄</param>
        public WpfAppEmbedder(System.Windows.FrameworkElement containerControl, IntPtr mainWindowHandle)
            : base(mainWindowHandle)
        {
            if (containerControl == null)
            {
                throw new ArgumentException(nameof(containerControl));
            }

            this._containerControl = containerControl;
        }





        /// <summary>
        /// 保持UI响应
        /// </summary>
        protected override void DoEvents()
        {

        }




        internal override EmbedContainerInfo GetEmbedContainerInfo()
        {
            // Put it into this form
            var hwndSource = System.Windows.PresentationSource.FromVisual(this._containerControl) as System.Windows.Interop.HwndSource;

            // Move the window to overlay it on this window
            var win = System.Windows.Window.GetWindow(this._containerControl);
            System.Windows.Point point = this._containerControl.TransformToAncestor(win).Transform(new System.Windows.Point(0, 0));
            return new EmbedContainerInfo(hwndSource.Handle, (int)point.X, (int)point.Y, (int)this._containerControl.ActualWidth, (int)this._containerControl.ActualHeight);
        }

        /// <summary>
        /// 进程启动完成
        /// </summary>
        /// <param name="mainWindowHandle">嵌套进程主窗口句柄</param>
        protected override void OnStarted(IntPtr mainWindowHandle)
        {
            //注册窗口控件大小改变及窗口控件所在窗口关闭事件
            this._containerControl.SizeChanged += this.ContainerControl_Resize;
            System.Windows.Window window = WindowsDesktopEx.WPF.WPFHelper.FindParentForm(this._containerControl);
            window.Closing += this.Window_Closing;
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            base.ContainerWindowClosing();
        }

        /// <summary>
        /// 窗口控件大小改变事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ContainerControl_Resize(object sender, EventArgs e)
        {
            var containerControl = sender as System.Windows.FrameworkElement;
            base.SetWindowSize((int)containerControl.ActualWidth, (int)containerControl.ActualHeight);
        }

        /// <summary>
        /// Dispose
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            this._containerControl.SizeChanged -= this.ContainerControl_Resize;
            System.Windows.Window window = WindowsDesktopEx.WPF.WPFHelper.FindParentForm(this._containerControl);
            window.Closing -= this.Window_Closing;


        }

    }

}
